package com.crazymakercircle.dhptester.distributed;

import com.crazymakercircle.constants.ServerConstants;
import com.crazymakercircle.entity.WorkerData;
import com.crazymakercircle.util.JsonUtil;
import com.crazymakercircle.util.ObjectUtil;
import com.crazymakercircle.util.ThreadUtil;
import com.crazymakercircle.zk.CuratorZKclient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;

import java.util.List;

/**
 * create by 尼恩 @ 疯狂创客圈
 **/
@Data
@Slf4j
public class WorkerManager
{
    //Zk客户端
    private CuratorFramework client = null;

    private String pathRegistered = null;
    private WorkerData node = null;


    private static WorkerManager singleInstance = null;
    private static final String path = ServerConstants.MANAGE_PATH;


    public synchronized static WorkerManager getInst()
    {
        if (null == singleInstance)
        {
            singleInstance = new WorkerManager();
        }
        return singleInstance;
    }

    private WorkerManager()
    {

    }

    private boolean inited = false;

    /**
     * 初始化节点管理
     */
    public synchronized void init()
    {

        if (inited)
        {
            return;
        }
        inited = true;

        try
        {
            if (null == client)
            {
                this.client = CuratorZKclient.instance.getClient();

            }

            //订阅节点的增加和删除事件

            PathChildrenCache childrenCache = new PathChildrenCache(client, path, true);
            PathChildrenCacheListener childrenCacheListener = new PathChildrenCacheListener()
            {

                @Override
                public void childEvent(CuratorFramework client,
                                       PathChildrenCacheEvent event) throws Exception
                {
                    log.info("开始监听其他的ImWorker子节点:-----");
                    ChildData data = event.getData();
                    switch (event.getType())
                    {
                        case CHILD_ADDED:
                            log.info("CHILD_ADDED : " + data.getPath() + "  数据:" + data.getData());
                            processNodeAdded(data);
                            break;
                        case CHILD_REMOVED:
                            log.info("CHILD_REMOVED : " + data.getPath() + "  数据:" + data.getData());
                            processNodeRemoved(data);
                            break;
                        case CHILD_UPDATED:
                            log.info("CHILD_UPDATED : " + data.getPath() + "  数据:" + new String(data.getData()));
                            break;
                        default:
                            log.debug("[PathChildrenCache]节点数据为空, path={}", data == null ? "null" : data.getPath());
                            break;
                    }

                }

            };

            childrenCache.getListenable().addListener(
                    childrenCacheListener, ThreadUtil.getIoIntenseTargetThreadPool());
            System.out.println("Register zk watcher successfully!");
            childrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);

        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private void processNodeRemoved(ChildData data)
    {

        byte[] payload = data.getData();
        WorkerData node = ObjectUtil.JsonBytes2Object(payload, WorkerData.class);

        String id = WorkerData.getIdByPath(data.getPath());
        node.setId(id);
        log.info("[TreeCache]节点删除, path={}, data={}",
                data.getPath(), JsonUtil.pojoToJson(node));


    }


    /**
     * 节点增加的处理
     *
     * @param data 新节点
     */
    private void processNodeAdded(ChildData data)
    {
        byte[] payload = data.getData();
        WorkerData node = ObjectUtil.JsonBytes2Object(payload, WorkerData.class);

        String id = WorkerData.getIdByPath(data.getPath());
        node.setId(id);

        log.info("[TreeCache]节点更新端口, path={}, data={}",
                data.getPath(), JsonUtil.pojoToJson(node));


    }

    /**
     * 查看Worker实例
     */
    public void viewWorker()
    {


        String managePath = ServerConstants.MANAGE_PATH;
        try
        {
            boolean exist = CuratorZKclient.getSingleton().isNodeExist(managePath);
            if (!exist)
            {
                System.out.println("no worker!");
                return;
            }

            List<String> list = CuratorZKclient.getSingleton().readChildren(managePath);
            if (null == list || list.size() < 1)
            {
                System.out.println("please start one worker first!");
                return;

            }
            for (String child : list)
            {
                String fullPath = managePath + "/" + child;
                System.out.println("fullPath = " + fullPath);
                String json = CuratorZKclient.getSingleton().readNode(fullPath);
                System.out.println("json = " + json);

            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
